home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / vbcc.lha / vbcc / pasm / output_abs.c < prev    next >
C/C++ Source or Header  |  1998-02-17  |  6KB  |  164 lines

  1. /* $VER: pasm output_abs.c V0.4 (05.07.97)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.4 (05.07.97) phx
  16.  *      Absolute output format supports correct relocations and
  17.  *      aligments. The user will be warned, if external references
  18.  *      are present.
  19.  * v0.2 (25.03.97) phx
  20.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  21.  *      or ELF output format may be selected. ELF is default for all
  22.  *      currently supported platforms. PPCasm supports nine different
  23.  *      relocation types (there are much more...).
  24.  *      Compiles and works also under NetBSD/amiga (68k).
  25.  *      Changed function declaration to 'new style' in all sources
  26.  *      (to avoid problems with '...' for example).
  27.  * v0.1 (11.03.97) phx
  28.  *      First test version with all PowerPC instructions and most
  29.  *      important directives. Only raw, absolute output.
  30.  * v0.0 (04.03.97) phx
  31.  *      File created.
  32.  */
  33.  
  34.  
  35. #define OUTPUT_ABS_C
  36. #include "ppcasm.h"
  37. #define BASEREG_OFFSET 0x7ffc  /* @@@ ? */
  38.  
  39.  
  40. void output_absolute(struct GlobalVars *);
  41. static void wr_err(struct GlobalVars *);
  42.  
  43.  
  44.  
  45. void output_absolute(struct GlobalVars *gv)
  46. {
  47.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  48.   struct Reloc *nextrel,*rel;
  49.   struct XReference *xref;
  50.   unsigned long offs = gv->absbase;
  51.   FILE *fp;
  52.  
  53.   /* calculate section base addresses */
  54.   while (nextsec = (struct Section *)sec->n.next) {
  55.     if (!(sec->flags & SF_DISCARD)) {
  56.       sec->index = (uint32)offs;
  57.       offs += (sec->size + 3) & ~3;
  58.     }
  59.     sec = nextsec;
  60.   }
  61.  
  62.   /* create output file */
  63.   sec = (struct Section *)gv->sectionlist.first;
  64.   if (fp = fopen(gv->dest_name,"w")) {
  65.     while (nextsec = (struct Section *)sec->n.next) {
  66.       if (!(sec->flags & SF_DISCARD) && sec->size) {
  67.  
  68.         /* try to resolve relocations */
  69.         rel = (struct Reloc *)sec->reloclist.first;
  70.         while (nextrel = (struct Reloc *)rel->n.next) {
  71.           uint32 *p = (uint32 *)((char *)sec->contents + rel->offset);
  72.           uint32 a = rel->relocsect->index + rel->addend;
  73.  
  74.           switch (rel->type) {
  75.             case R_PPC_ADDR32:
  76.               *p = ECVW(a);
  77.               break;
  78.             case R_PPC_ADDR16:
  79.               *(uint16 *)p = ECVH((uint16)a);
  80.               break;
  81.             case R_PPC_ADDR16_LO:
  82.               *(uint16 *)p = ECVH((uint16)(a & 0xffff));
  83.               break;
  84.             case R_PPC_ADDR16_HA:
  85.               if (a & 0x8000)
  86.                 a += 0x10000;
  87.             case R_PPC_ADDR16_HI:
  88.               *(uint16 *)p = ECVH((uint16)(a >> 16));
  89.               break;
  90.             case R_PPC_ADDR24:
  91.               *p = ECVW((uint32)((*(uint8 *)p & 0xfc) << 24) |
  92.                         (a & 0x3fffffc) | (uint32)(*((uint8 *)p+3) & 3));
  93.               break;
  94.             case R_PPC_ADDR14:
  95.             case R_PPC_ADDR14_BRTAKEN:
  96.             case R_PPC_ADDR14_BRNTAKEN:
  97.               *((uint16 *)p+1) = ECVH((uint16)(a & 0xfffc) |
  98.                                       (uint16)(*((uint8 *)p+3) & 3));
  99.               break;
  100.             case R_PPC_REL24:
  101.               *p = ECVW((uint32)((*(uint8 *)p & 0xfc) << 24) |
  102.                         ((a - (sec->index + rel->offset)) & 0x3fffffc) |
  103.                         (uint32)(*((uint8 *)p+3) & 3));
  104.               break;
  105.             case R_PPC_REL14:
  106.             case R_PPC_REL14_BRTAKEN:
  107.             case R_PPC_REL14_BRNTAKEN:
  108.               *((uint16 *)p+1) = ECVH((uint16)((a - (sec->index + 
  109.                                       rel->offset - 2)) & 0xfffc) |
  110.                                       (uint16)(*((uint8 *)p+3) & 3));
  111.               break;
  112.             case R_PPC_REL32:
  113.               *p = ECVW(a - (sec->index + rel->offset));
  114.               break;
  115.             case R_PPC_TOC16:
  116.               if (gv->tocsect)
  117.                 a -= gv->tocsect->index + BASEREG_OFFSET;
  118.               else
  119.                 a -= BASEREG_OFFSET;
  120.               *(uint16 *)p = ECVH((uint16)a);
  121.               break;
  122.             default:
  123.               error(53,elfrel_name[rel->type & ELFRELNAMMSK],rel->offset,
  124.                     sec->name);  /* relocation not supported */
  125.               break;
  126.           }
  127.           rel = nextrel;
  128.         }
  129.  
  130.         /* any external references? (would be difficult here :) */
  131.         while (xref = (struct XReference *)remhead(&sec->xreflist))
  132.           error(55,xref->xsymbol->name);  /* no xrefs in absolute output */
  133.  
  134.         /* write section contents */
  135.         if (sec->flags & SF_UNINITIALIZED) {  /* bss section */
  136.           unsigned long s = (sec->size + 3) >> 2;
  137.           while (s--) {
  138.             if (!fwrite(gv->alignment_bytes,1,4,fp))
  139.               wr_err(gv);
  140.           }
  141.         }
  142.         else {
  143.           if (!fwrite(sec->contents,1,sec->size,fp))
  144.               wr_err(gv);
  145.           if ((4-(sec->size&3))&3) {  /* aligment */
  146.             if (!fwrite(gv->alignment_bytes,1,(4-(sec->size&3))&3,fp))
  147.                 wr_err(gv);
  148.           }
  149.         }
  150.       }
  151.       sec = nextsec;
  152.     }
  153.     fclose(fp);
  154.   }
  155.   else
  156.     error(25,gv->dest_name);  /* unable to create output file */
  157. }
  158.  
  159.  
  160. static void wr_err(struct GlobalVars *gv)
  161. {
  162.   error(26,gv->dest_name);  /* write error */
  163. }
  164.